﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using Catering;
using System.Threading;
using System.Configuration;

namespace Catering
{
    public partial class Download : System.Web.UI.Page
    {
        public void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                if (!string.IsNullOrEmpty(Request.QueryString["topurl"]) && !string.IsNullOrEmpty(Request.QueryString["topname"]))
                {
                    string topurl = Request.QueryString["topurl"];
                    string topname = Request.QueryString["topname"];
                    string pathtype = Request.QueryString["toppathtype"];
                    string path = "./UpFile/";
                    string url = HttpUtility.UrlDecode(topurl);
                    string name = HttpUtility.UrlDecode(topname);
                    pathtype = pathtype == "books" ? ConfigurationManager.AppSettings["FileRoot"] : "";
                    path = string.IsNullOrEmpty(pathtype) ? Server.MapPath(path + url) : pathtype + url;
                    //FileInfo fileInfo = new FileInfo(Server.MapPath("./UpFile/" + url));
                    //Response.Clear();
                    //Response.ClearContent();
                    //Response.ClearHeaders();
                    //if (Request.UserAgent.ToLower().IndexOf("firefox") > -1)
                    //{
                    //    Response.AddHeader("Content-Disposition", "attachment;filename=\"" + HttpUtility.UrlEncode(name, System.Text.Encoding.UTF8) + "\"");
                    //}
                    //else
                    //{
                    //    Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(name, System.Text.Encoding.UTF8));
                    //}
                    ////Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(name,System.Text.Encoding.UTF8));
                    //Response.AddHeader("Content-Length", fileInfo.Length.ToString());
                    //Response.AddHeader("Content-Transfer-Encoding", "binary");
                    //Response.ContentType = "application/octet-stream";
                    //Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
                    //Response.WriteFile(fileInfo.FullName);
                    //Response.Flush();
                    //Response.End();
                    Page.Response.Clear();
                    bool success = ResponseFile(Page.Request, Page.Response, name, path, 1024000);
                    if (!success) Response.Write("下载文件出错！");
                    Page.Response.End();
                }
            }
        }
        private void FileDownload(string fName, string path)
        {
            long lngFileSize;
            byte[] bytBuffer;
            int iReading;
            string sFileName = Server.MapPath(path + fName);
            Stream outStream = Response.OutputStream;
            Response.ContentType = "application/octet-stream";
            Response.AppendHeader("Connection", "keep-alive");
            Response.AppendHeader("Content-Disposition", "     attachment;     filename     =     " + fName);
            FileStream fStream = new FileStream(sFileName, FileMode.OpenOrCreate, FileAccess.Read);
            lngFileSize = fStream.Length;
            bytBuffer = new byte[(int)lngFileSize];
            while ((iReading = fStream.Read(bytBuffer, 0, (int)lngFileSize)) > 0)
            {
                outStream.Write(bytBuffer, 0, iReading);
            }
            fStream.Close();
            outStream.Close();
        }

        ///   <summary>  
        ///   文件下载  
        ///   </summary>  
        ///   <param   name="FullFileName">包括路径在内的文件名</param>  
        public static void FileDownloadByFullName(string FullFileName)
        {
            FileInfo DownloadFile = new FileInfo(FullFileName);
            HttpContext.Current.Response.Clear();
            HttpContext.Current.Response.ClearHeaders();
            HttpContext.Current.Response.Buffer = false;
            HttpContext.Current.Response.ContentType = "application/octet-stream";
            HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(DownloadFile.FullName, System.Text.Encoding.ASCII));
            HttpContext.Current.Response.AppendHeader("Content-Length", DownloadFile.Length.ToString());
            HttpContext.Current.Response.WriteFile(DownloadFile.FullName);
            HttpContext.Current.Response.Flush();
            HttpContext.Current.Response.End();
        }

        //   输出硬盘文件，提供下载  
        //   输入参数   _Request:   Page.Request对象，   _Response:   Page.Response对象，   _fileName:   下载文件名，   _fullPath:   带文件名下载路径，   _speed   每秒允许下载的字节数  
        //   返回是否成功  
        public static bool ResponseFile(HttpRequest _Request, HttpResponse _Response, string _fileName, string _fullPath, long _speed)
        {
            try
            {
                FileStream myFile = new FileStream(_fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                BinaryReader br = new BinaryReader(myFile);
                try
                {
                    _Response.AddHeader("Accept-Ranges", "bytes");
                    _Response.Buffer = false;
                    long fileLength = myFile.Length;
                    long startBytes = 0;

                    int pack = 10240;   //10K   bytes  
                    //int   sleep   =   200;   //每秒5次   即5*10K   bytes每秒  
                    int sleep = (int)Math.Floor(1000 * pack / Convert.ToDecimal(_speed)) + 1;
                    if (_Request.Headers["Range"] != null)
                    {
                        _Response.StatusCode = 206;
                        string[] range = _Request.Headers["Range"].Split(new char[] { '=', '-' });
                        startBytes = Convert.ToInt64(range[1]);
                    }
                    _Response.AddHeader("Content-Length", (fileLength - startBytes).ToString());
                    if (startBytes != 0)
                    {
                        _Response.AddHeader("Content-Range", string.Format("   bytes   {0}-{1}/{2}", startBytes, fileLength - 1, fileLength));
                    }
                    _Response.AddHeader("Connection", "Keep-Alive");
                    _Response.ContentType = "application/octet-stream";
                    _Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(_fileName, System.Text.Encoding.UTF8));

                    br.BaseStream.Seek(startBytes, SeekOrigin.Begin);
                    int maxCount = (int)Math.Floor((fileLength - startBytes) / Convert.ToDecimal(pack)) + 1;

                    for (int i = 0; i < maxCount; i++)
                    {
                        if (_Response.IsClientConnected)
                        {
                            _Response.BinaryWrite(br.ReadBytes(pack));
                            Thread.Sleep(sleep);
                        }
                        else
                        {
                            i = maxCount;
                        }
                    }
                }
                catch
                {
                    return false;
                }
                finally
                {
                    br.Close();
                    myFile.Close();
                }
            }
            catch
            {
                return false;
            }
            return true;
        }
    }
}